package com.blog.user.controller;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.blog.redis.RedisUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tcj.blog.controller.ControllerUtil;
import com.tcj.blog.controller.DoThing;
import com.tcj.blog.domain.MessageBoard;
import com.tcj.blog.domain.User;
import com.tcj.blog.dto.*;
import com.blog.file.HeaderUtil;
import com.tcj.blog.service.IMessageBoardService;
import com.tcj.blog.service.IUserService;
import com.blog.sms.SendSmsUtil;
import com.blog.token.TokenUtil;
import com.blog.validation.ValidationUtil;
import com.tcj.blog.vo.MessageBoardVO;
import io.jsonwebtoken.Claims;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.UUID;
/**
 * @author tcj
 * @date 2020/9/30 17:23
 */
@RestController
@CrossOrigin
@Api(tags = "用户功能接口")
public class UserController   {
    private static final long TOKEN_VALID_TIME = 60 * 60 * 24;
    @Autowired
    private IUserService userService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private IMessageBoardService messageBoardService;
    private ObjectMapper objectMapper = new ObjectMapper();
    @ApiOperation(value = "用户登录", notes = "传入的参数全是非空")
    @PostMapping("/login")
    public JsonResult login(@Validated @RequestBody LoginUser loginUser, BindingResult bindingResult) {
        //创建dto
        JsonResult jsonResult = new JsonResult();
        //判断传入的参数是否符合验证
        if (bindingResult.hasErrors()) {
            //不符合则不查询数据库
            jsonResult.setStatus(ResponseCode.BAD_REQUEST);
            jsonResult.setError(ValidationUtil.getErrorMessage(bindingResult));
            jsonResult.setMessage("账号或密码不能为空！");

        } else {
            jsonResult = ControllerUtil.getResult(new DoThing() {
                @Override
                public void doThing(JsonResult jsonResult) {
                    //查询数据库
                    User users = userService.loginUser(loginUser);
                    if (users == null){
                        jsonResult.setStatus(ResponseCode.NOT_TRUE);
                        jsonResult.setMessage("账号或密码错误！");
                    }else {
                        jsonResult.setStatus(ResponseCode.OK);
                        users.setPassword(null);
                        String token = TokenUtil.getToken(users);
                        //将token放入redis中
                        try {
                            redisUtil.set(token,objectMapper.writeValueAsString(users),TOKEN_VALID_TIME);
                            jsonResult.setData(users);
                            jsonResult.setToken(token);
                        } catch (JsonProcessingException e) {
                           jsonResult.setStatus(ResponseCode.ERROR);
                        }
                    }
                }
            });
        }
        return jsonResult;
    }

    @ApiOperation(value = "用户使用短信验证码登录")
    @PostMapping("/loginPhone")
    public JsonResult loginPhone(@RequestParam String phone ,@RequestParam String num) {
        //在redis中获取是否有该验证码
        JsonResult jsonResult = new JsonResult();
        Object req = redisUtil.get(phone);
        if (req != null && req.toString().equals(num) ){
            //查询数据库
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("phone",phone);
            User user = userService.getOne(queryWrapper);
            if (user == null){
                jsonResult.setStatus(ResponseCode.ERROR);
            }else {
                user.setPassword("");
                String token = TokenUtil.getToken(user);
                try {
                    redisUtil.set(token,objectMapper.writeValueAsString(user),TOKEN_VALID_TIME);
                    jsonResult.setStatus(ResponseCode.OK);
                    jsonResult.setToken(token);
                    jsonResult.setMessage("登录成功！");
                } catch (JsonProcessingException e) {
                    jsonResult.setStatus(ResponseCode.ERROR);
                }
            }
            redisUtil.del(num);
        }else {
            jsonResult.setStatus(ResponseCode.NOT_TRUE);
            jsonResult.setMessage("验证码不正确!");
        }
        return jsonResult;
    }

    @ApiOperation(value = "用户注册")
    @PostMapping("/register")
    public JsonResult register(@RequestBody RegisterUser user) {
        JsonResult jsonResult = new JsonResult();
        UUID uuid = UUID.randomUUID();
        //判断验证码是否正确
        if (user != null) {
            //判断验证码是否正确
            Object o = redisUtil.get(user.getPhone());
            if (o != null &&  o.toString().equals(user.getValid())){
                try {
                    user.setName(uuid.toString().split("-")[0]);
                    user.setSex("男");
                    userService.save(user);
                    jsonResult.setStatus(ResponseCode.OK);
                    jsonResult.setMessage("注册成功！");
                } catch (Exception e) {
                    jsonResult.setStatus(ResponseCode.ERROR);
                    jsonResult.setMessage("未知错误,请联系管理员!");
                }
                redisUtil.del(user.getPhone());
            }else {
                jsonResult.setStatus(ResponseCode.NOT_TRUE);
                jsonResult.setMessage("验证码不正确！");
            }
        } else {
            jsonResult.setStatus(ResponseCode.BAD_REQUEST);
            jsonResult.setMessage("注册失败,请输入有效的数据!!!");
        }
        return jsonResult;
    }
    @PostMapping("/validPhone")
    @ApiOperation("获取手机号是否已经注册")
    public JsonResult validPhone(@RequestBody String param){
        JSONObject jsonObject = JSONObject.parseObject(param);
        String phone = jsonObject.getString("phone");
        JsonResult jsonResult = new JsonResult();
        if (null != phone && !"".equals(phone) && phone.length() == 11){
               QueryWrapper<User> queryWrapper = new QueryWrapper<>();
               queryWrapper.eq("phone",phone);
               User user = userService.getOne(queryWrapper);
               if (user != null){
                   jsonResult.setStatus(ResponseCode.NOT_TRUE);
                   jsonResult.setMessage("该手机号已被注册!");
               }else {
                   jsonResult.setStatus(ResponseCode.OK);
                   jsonResult.setMessage("验证码发送成功!");
               }
        }else {
            jsonResult.setStatus(ResponseCode.BAD_REQUEST);
            jsonResult.setMessage("输入手机号格式有误!");
        }
        return jsonResult;
    }
    @PostMapping("/loginuser")
    @ApiOperation("验证登录token是否已失效")
    public JsonResult loginUser(HttpServletRequest httpServletRequest){
        JsonResult jsonResult = new JsonResult();
        String token = httpServletRequest.getHeader("token");
        if ("null".equals(token)){
            jsonResult.setStatus(ResponseCode.NOT_TRUE);
            return jsonResult;
        }
        //判断token是否在黑名单,未加reids时的解决方案
//        if (TokenUtil.verifyToken(token)){
//            jsonResult.setStatus(ResponseCode.UNAUTHORIZED);
//            jsonResult.setMessage("登录失效,请重新登录!");
//            return  jsonResult;
//        }
        //判断是否有该token
        Object o = redisUtil.get(token);
        if (o == null){
            jsonResult.setStatus(ResponseCode.UNAUTHORIZED);
            jsonResult.setMessage("登录失效,请重新登录!");
            return  jsonResult;
        }
        //这里可以直接将用户存入redis 懒得改了 还是解析token
        Claims claims = TokenUtil.validToken(token);
        if (claims != null){
            Object headers = claims.get("header");
            Object id = claims.get("id");
            Object name = claims.get("name");
            User user = new User();
            user.setName(name.toString());
            user.setHeader(headers.toString());
            user.setId(Integer.parseInt(id.toString()));
            jsonResult.setData(user);
            jsonResult.setStatus(ResponseCode.OK);
        }else {
            jsonResult.setStatus(ResponseCode.UNAUTHORIZED);
            jsonResult.setMessage("登录过期,请重新登录!");
        }
        return jsonResult;
    }
    @ApiOperation("用户参与评论")
    @PostMapping("/comment")
    public JsonResult addComment(@RequestBody UserData userData){
        Object comment =  userData.getOtherData();
       if (comment == null || "".equals(comment.toString())){
           JsonResult jsonResult = new JsonResult();
           jsonResult.setData(ResponseCode.BAD_REQUEST);
           jsonResult.setMessage("内容不能为空!!!");
           return jsonResult;
       }
       return ControllerUtil.getResult(new DoThing() {
           @Override
           public void doThing(JsonResult jsonResult) {
                MessageBoard messageBoard = new MessageBoard();
                messageBoard.setCreateTime(LocalDateTime.now());
                messageBoard.setContent(userData.getOtherData().toString());
                messageBoard.setUserId(userData.getId());
                messageBoard.setUserName(userData.getName());
                messageBoard.setUserHeader(userData.getHeader());
                messageBoard.setParentId(userData.getParentId());
                messageBoard.setBlogId(userData.getBlogId());
               boolean save = messageBoardService.save(messageBoard);

               if (save){
                   MessageBoardVO messageBoardVO = (MessageBoardVO) ControllerUtil.copyData(messageBoard,new MessageBoardVO());
                   messageBoardVO.setMessageRole(messageBoardService.getRole(messageBoard.getUserId()));
                   messageBoardVO.setSubMessageBoard(new ArrayList<>());
                   jsonResult.setStatus(ResponseCode.OK);
                   jsonResult.setData(messageBoardVO);
                   jsonResult.setMessage("发表成功！");
               }else {
                   jsonResult.setStatus(ResponseCode.ERROR);
                   jsonResult.setMessage("发表失败，请联系管理员");
               }
           }
       });
    }
    @ApiOperation("用户退出登录")
    @PostMapping("/logout")
    public JsonResult logout(HttpServletRequest httpServletRequest){
        String token = httpServletRequest.getHeader("token");
       // TokenUtil.addBlackList(token);
        redisUtil.del(token);
        return ControllerUtil.getResult(new DoThing(){});
    }

    @ApiOperation("验证用户注册的账号是否已存在")
    @PostMapping("/checkAcc")
    public JsonResult checkAcc(@RequestBody String account){
        return ControllerUtil.getResult(new DoThing() {
            @Override
            public void doThing(JsonResult jsonResult) {
                if (account == null || "".equals(account.trim())){
                    jsonResult.setStatus(ResponseCode.BAD_REQUEST);
                    jsonResult.setMessage("请求参数错误！");
                }else {
                    boolean succ = userService.checkAcc(account);
                    if (succ){
                        jsonResult.setStatus(ResponseCode.NOT_TRUE);
                    }else {
                        jsonResult.setStatus(ResponseCode.OK);
                    }
                }
            }
        });
    }
    @ApiOperation("发送手机验证码")
    @PostMapping("/sendSms")
    public JsonResult sendSms(@RequestBody String phone){
        //随机验证码
        int random = RandomUtils.nextInt(19875,99999);
        String content = "您的验证码是"+ random +"，在3分钟内输入有效。如非本人操作请忽略此短信。";
        return ControllerUtil.getResult(new DoThing() {
            @Override
            public void doThing(JsonResult jsonResult) {
                if (phone == null || "".equals(phone) || phone.length() != 11){
                    jsonResult.setStatus(ResponseCode.BAD_REQUEST);
                    jsonResult.setMessage("请求参数错误！！");
                }else {
                    boolean succ = SendSmsUtil.sendSms(phone, content);
                    redisUtil.set(phone,random,60 * 3);
                    if (succ){
                        jsonResult.setStatus(ResponseCode.OK);
                        jsonResult.setMessage("短信发送成功！");
                    }else {
                        jsonResult.setStatus(ResponseCode.BAD_REQUEST);
                        jsonResult.setMessage("短信发送失败,请联系管理员!");
                    }
                }
            }
        });
    }

    @ApiOperation("根据token获取用户信息")
    @PostMapping("/getInfo")
    public JsonResult getUserInfo(HttpServletRequest request){

      return   ControllerUtil.getResult(new DoThing() {
            @Override
            public void doThing(JsonResult jsonResult) {
                String token = request.getHeader("token");
                Claims claims = TokenUtil.validToken(token);
                User user = (User) TokenUtil.getInfo(new User(), claims);
                jsonResult.setStatus(ResponseCode.OK);
                jsonResult.setData(user);
            }
        });
    }

    @ApiOperation("修改用户信息")
    @PostMapping("/changeUser")
    public JsonResult changeUser(@RequestBody User user,HttpServletRequest request){
        return ControllerUtil.getResult(new DoThing() {
            @Override
            public void doThing(JsonResult jsonResult) {

                if (user.getHeader() != null && !"".equals(user.getHeader())){
                    HeaderUtil.getHeader(user.getHeader());
                }
                boolean succ =  userService.changeUser(user);
               if (succ){
                   User newUser = userService.getById(user.getId());
                   String token = TokenUtil.getToken(newUser);
                   redisUtil.del(request.getHeader("token"));
                   try {
                       redisUtil.set(token,objectMapper.writeValueAsString(newUser),TOKEN_VALID_TIME);
                       jsonResult.setData(newUser);
                       jsonResult.setMessage("修改成功!");
                       jsonResult.setStatus(ResponseCode.OK);
                       jsonResult.setToken(token);
                   } catch (JsonProcessingException e) {
                       jsonResult.setStatus(ResponseCode.ERROR);
                   }

               }
            }
        });
    }
}
